package managesystem;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import javax.persistence.Id;

import tracksystem.Activity;
import tracksystem.OtherActivity;
import tracksystem.SchoolActivity;

import com.googlecode.objectify.annotation.Indexed;
import com.googlecode.objectify.annotation.Serialized;
import com.googlecode.objectify.annotation.Unindexed;

import controlsystem.Badge;
import controlsystem.Course;
import controlsystem.Milestone;

/**
 * Stelt een student voor
 * 
 * @author Incalza Dario & Stijn Hoskens
 * 
 */
@Unindexed
public class Student implements Serializable{

        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        @Id
        private Long id;
        @Indexed
        private String username;
        private String fname;
        private String lname;
        private String email;
        private String password;
        @Serialized
        private List<Course> courses = new ArrayList<Course>();
        @Serialized
        private List<Buddy> buddies = new ArrayList<Buddy>();
        @Serialized
        private List<Badge> badges = new ArrayList<Badge>();
        @Serialized
        private List<Activity> activities = new ArrayList<Activity>();
        private List<String> places = new ArrayList<String>();
        private List<String> aidTools = new ArrayList<String>();
        private List<String> distractions = new ArrayList<String>();
        @Serialized
        private List<Milestone> milestones = new ArrayList<Milestone>();
        @Serialized
        private Activity unfinishedActivity = null;
        @SuppressWarnings("unused")
        private Student() {

        }

        /**
         * Maak een nieuwe student aan
         * 
         * @param fn
         * @param ln
         * @param email
         * @param un
         * @param pw
         */
        public Student(String fn, String ln, String email, String un, String pw) {

                this.setFname(fn);
                this.setLname(ln);
                this.setEmail(email);
                this.setUsername(un);
                this.setPassword(pw);

        }

        /**
         * vraag de username van de student
         * 
         * @return de username van de student
         */
        public String getUsername() {
                return username;
        }

        /**
         * verander de username
         * 
         * @param username
         */
        public void setUsername(String username) {
                this.username = username;
        }

        /**
         * vraag the voornaam op
         * 
         * @return the fname
         */
        public String getFname() {
                return fname;
        }

        /**
         * verander de voornaam
         * 
         * @param fname
         *            the fname to set
         */
        public void setFname(String fname) {
                this.fname = fname;
        }

        /**
         * vraag de achternaam op
         * 
         * @return the lname
         */
        public String getLname() {
                return lname;
        }

        /**
         * verander de laatste naam
         * 
         * @param lname
         *            the lname to set
         */
        public void setLname(String lname) {
                this.lname = lname;
        }

        /**
         * vraag het e-mail adres op
         * 
         * @return the email
         */
        public String getEmail() {
                return email;
        }

        /**
         * verander het e-mail adres.
         * 
         * @param email
         *            the email to set
         */
        public void setEmail(String email) {
                this.email = email;
        }

        /**
         * vraag het wachtwoord op.
         * 
         * @return the password
         */
        public String getPassword() {
                return password;
        }

        /**
         * verander het wachtwoord.
         * 
         * @param password
         *            the password to set
         */
        public void setPassword(String password) {
                this.password = password;
        }

        /**
         * Vraag de vakken op dat de student volgt.
         * 
         * @return the courses
         */
        public List<Course> getCourses() {
                return courses;
        }

        /**
         * Voeg een vak toe aan de lijst van de student
         * 
         * @param course
         */
        public void addCourse(Course c) {
                courses.add(c);
        }

        /**
         * Vraag de vrienden van de student op.
         * 
         * @return the buddies
         */
        public List<Buddy> getBuddies() {
                
                return buddies;
        }

        /**
         * Voeg een vriend toe.
         * 
         * @param buddy
         */
        public void addBuddy(Buddy buddy) {
                buddies.add(buddy);
        }
        
        /**
         * get deleteable buddies
         */
        public List<Buddy> getdeleteableBuddies(){
                List<Buddy> deleteableBuddies = new ArrayList<Buddy>();
                Iterator<Buddy> iteratorD = buddies.iterator();
                while(iteratorD.hasNext()){
                        Buddy buddy = iteratorD.next();
                        boolean found = false;
                        Iterator<Activity> iteratorA = activities.iterator();
                        while(iteratorA.hasNext()){
                                Activity activity = iteratorA.next();
                                if(activity.getBuddylist().contains(buddy)){
                                        found = true;
                                }
                        }
                        if (found == false){
                                deleteableBuddies.add(buddy);
                        }
                }
                return deleteableBuddies;
        }
        
        /**
         * Verwijder een vriend.
         * 
         * @param buddy
         * @return true wanneer de buddy is verwijderd, false wanneer hij niet
         *         verwijderd is
         */
        public boolean deleteBuddy(String firstname, String lastname) {
                boolean deleted = false;
                Iterator<Buddy> delBuddies = buddies.iterator();
                while(delBuddies.hasNext()){
                        Buddy buddy = delBuddies.next();
                        if(buddy.getFirstname().equals(firstname) && buddy.getLastname().equals(lastname) && Buddy.controlBuddyList(getdeleteableBuddies(),buddy)){
                                delBuddies.remove();
                                deleted = true;
                        }
                }
                return deleted;
        }



        /**
         * vraagt de badges van de student op.
         * 
         * @return de badges
         */
        public Collection<Badge> getBadges() {
                return badges;
        }

        /**
         * vervangt de gehele lijst van badges
         * 
         * @param badges
         *            de nieuwe collectie
         */
        public void setBadges(List<Badge> badges) {
                this.badges = badges;
        }

        /**
         * voegt een badge toe
         * 
         * @param b
         *            de badge die toegevoegd moet worden
         */
        public void addBadge(Badge b) {
                badges.add(b);
        }

        /**
         * Haal de activiteiten op die bij de student horen.
         * 
         * @return the activities
         */
        public List<Activity> getAct() {
                
                return activities;
        }

        /**
         * Vervangt de hele opgeslagen lijst van activities
         * 
         * @param activities
         *            de nieuwe lijst
         */
        public void setActs(List<Activity> activities) {
                activities.clear();
                this.activities = activities;
                
        }

        /**
         * voegt een activity toe
         * 
         * @param a
         *            de activity die toegevoegd moet worden
         */
        public void addActivity(Activity a) {
                activities.add(a);
                
                addPlace(a.getPlace());
                
                for(String d : a.getDistractions()){
                        addDistraction(d);
                }
                
                for(String aid : a.getAidTools()){
                        addAid(aid);
                }
                
                unfinishedActivity = null;
        }

        /**
         * vraagt de milestones op
         * 
         * @return de milestones
         */
        public ArrayList<Milestone> getMilestones() {
                return (ArrayList<Milestone>) milestones;
        }

        /**
         * vervangt de gehele lijst van milestones
         * 
         * @param milestones
         *            de nieuwe collectie
         */
        public void setMilestones(List<Milestone> milestones) {
                this.milestones = milestones;
        }

        /**
         * voegt een milestone toe
         * 
         * @param m
         *            de milestone die toegevoegd moet worden
         */
        public void addMilestone(Milestone m) {
                milestones.add(m);
        }

        /**
         * vraag het object-id op .
         * 
         * @return the id
         */
        public Long getId() {
                return id;
        }

        /**
         * Voegt een nieuwe plaats toe
         * @return boolean met true als de plaats is toegevoegd (wanneer false is de plaats al tegoevoegd)
         */
        public boolean addPlace(String place) {
                boolean added = false;
                if(places.contains(place) == false){
                        places.add(place);
                        added = true;
                }
                return added;
        }
        
        /**
         * retourneert de plaatsen
         * @return
         */
        public String[] getPlaces() {
                String[] placesArray = new String[places.size()];
                places.toArray(placesArray);
                return placesArray;
        }
        
        /**
         * get deleteable places
         */
        public List<String> getdeleteablePlaces(){
                List<String> deleteablePlaces = new ArrayList<String>();
                Iterator<String> iteratorD = places.iterator();
                while(iteratorD.hasNext()){
                        String place = iteratorD.next();
                        boolean found = false;
                        Iterator<Activity> iteratorA = activities.iterator();
                        while(iteratorA.hasNext()){
                                Activity activity = iteratorA.next();
                                if(activity.getPlace()!=null){
                                if(activity.getPlace().equals(place)){
                                        found = true;
                                }}
                        }
                        if (found == false){
                                deleteablePlaces.add(place);
                        }
                }
                return deleteablePlaces;
        }
        
        /**
         * Verwijder een plaats.
         * 
         * @param place
         * @return true wanneer de plaats is verwijderd, false wanneer hij niet verwijderd is
         */
        public boolean deletePlace(String place) {
                boolean deleted = false;
                if(getdeleteablePlaces().contains(place)){
                        places.remove(place);
                        deleted = true;
                }
                return deleted;
        }

        /**
         * toevoegen van een aidtool
         * @return boolean met true wanneer de aidtool is toegevoegd (wanneer false is hij al tegoevoegd)
         */
        public boolean addAid(String aidTool){
                boolean added = false;
                if(aidTools.contains(aidTool) == false){
                        aidTools.add(aidTool);
                        added = true;
                }
                return added;
        }
        
        /**
         * retourneert de aidtools
         * @return een lijst van aidtools
         */
        public String[] getAids() {
                String[] aidsArray = new String[aidTools.size()];
                aidTools.toArray(aidsArray);
                return aidsArray;
        }

        /**
         * get deleteable aidtools
         */
        public List<String> getdeleteableAidTools(){
                List<String> deleteableAids = new ArrayList<String>();
                Iterator<String> iteratorD = aidTools.iterator();
                while(iteratorD.hasNext()){
                        String aidtool = iteratorD.next();
                        boolean found = false;
                        Iterator<Activity> iteratorA = activities.iterator();
                        while(iteratorA.hasNext()){
                                Activity activity = iteratorA.next();
                                if(activity.getAidTools().contains(aidtool)){
                                        found = true;
                                }
                        }
                        if (found == false){
                                deleteableAids.add(aidtool);
                        }
                }
                return deleteableAids;
        }
        
        /**
         * Verwijder een aidTool.
         * 
         * @param aidTool
         * @return true wanneer de aidTool is verwijderd, false wanneer hij niet verwijderd is
         */
        public boolean deleteAidTool(String aidTool) {
                boolean deleted = false;
                if(getdeleteableAidTools().contains(aidTool)){
                        aidTools.remove(aidTool);
                        deleted = true;
                }
                return deleted;
        }
        
        /**
         * voegt een afleiding toe
         * @return boolean met true wanneer de afleiding is toegevoegd (wanneer false is hij al tegoevoegd)
         */
        public boolean addDistraction(String distraction){
                boolean added = false;
                if(distractions.contains(distraction) == false){
                        distractions.add(distraction);
                        added = true;
                }
                return added;
        }
        
        /**
         * 
         * @return
         */
        public String[] getDistractions() {
                String[] distractionsArray = new String[distractions.size()];
                distractions.toArray(distractionsArray);
                return distractionsArray;
        }
        
        /**
         * getDeleteable distractions
         */
        public List<String> getdeleteableDistractions(){
                List<String> deleteableDistr = new ArrayList<String>();
                Iterator<String> iteratorD = distractions.iterator();
                while(iteratorD.hasNext()){
                        String distraction = iteratorD.next();
                        boolean found = false;
                        Iterator<Activity> iteratorA = activities.iterator();
                        while(iteratorA.hasNext()){
                                Activity activity = iteratorA.next();
                                if(activity.getDistractions().contains(distraction)){
                                        found = true;
                                }
                        }
                        if (found == false){
                                deleteableDistr.add(distraction);
                        }
                }
                return deleteableDistr;
        }
        
        /**
         * Verwijder een distractions.
         * 
         * @param aidTool
         * @return true wanneer de aidTool is verwijderd, false wanneer hij niet verwijderd is
         */
        public boolean deleteDistraction(String distraction) {
                boolean deleted = false;
                if( getdeleteableDistractions().contains(distraction)){
                        distractions.remove(distraction);
                        deleted = true;
                }
                return deleted;
        }
        
        /**
         * @return the unfinishedActivity
         */
        public Activity getUnfinishedActivity() {
                return unfinishedActivity;
        }

        /**
         * @param unfinishedActivity the unfinishedActivity to set
         */
        public void setUnfinishedActivity(Activity unfinishedActivity) {
                this.unfinishedActivity = unfinishedActivity;
        }
        
        public void deleteCourse(String courseName){
                
                deleteActivities(courseName);// delete all the activities associated with the course that will be removed
                deleteMilestones(courseName);// delete all the milestones associated with the course that will be removed
                Iterator<Course> iter = courses.iterator();
                while(iter.hasNext()){
                        Course c = iter.next();
                        if(c.getName().equals(courseName)){
                                iter.remove();
                                break;
                        }
                }
        }
        /**
         * Delete all activities asscociated with a certain course that will be deleted.
         * @param courseName
         */
        private void deleteActivities(String courseName){
                
                Iterator<Activity> iter = activities.iterator();
                while(iter.hasNext()){
                        Activity a = iter.next();
                        if(a instanceof SchoolActivity){
                                
                                if(((SchoolActivity) a).getCourse().getName().equals(courseName)){
                                        iter.remove();
                                }
                                
                        }
                }
                
        }
        /**
         * Delete all milestones associated with a certain course that will be deleted.
         * @param courseName
         */
        private void deleteMilestones(String courseName){
                
                Iterator<Milestone> iter = milestones.iterator();
                while(iter.hasNext()){
                        Milestone m = iter.next();
                        if(m.getCourse().getName().equals(courseName)){
                                iter.remove();
                        }
                }
        }
        
        public void addMobileActivity(Activity a){
                activities.add(a);
        }
        
        public ArrayList<SchoolActivity> getOnlySchoolActs(){
        	ArrayList<SchoolActivity> SAs = new ArrayList<SchoolActivity>();
        	for(Activity a : activities){
        		if(a instanceof SchoolActivity){
        			SAs.add((SchoolActivity) a);
        		}
        	}
        	
        	return SAs;
        }
        
        public ArrayList<OtherActivity> getOnlyOtherActs(){
        	ArrayList<OtherActivity> OAs = new ArrayList<OtherActivity>();
        	for(Activity a : activities){
        		if(a instanceof OtherActivity){
        			OAs.add((OtherActivity) a);
        		}
        	}
        	
        	return OAs;
        }
        
        public boolean deleteActivity(int Id){
        	boolean deleted = false;
        	Iterator<Activity> iter = activities.iterator();
        	while(iter.hasNext()){
        		Activity a = iter.next();
        		if(a.hashCode()==Id){
        			iter.remove();
        			deleted = true;
        			break;
        		}
        	}
        	
        	return deleted;
        }

        
        
}
